import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.HashMultimap;

import java.util.*;

public class Biblioteca {

    public static final String WELCOME_MESSAGE = "Welcome,this is Biblioteca app!";
    public static final String MOVIE = "Movie";
    public static final String BOOK = "Book";
    public static final int INVALIDE_ID = 0;
    private HashMultimap<String, Resource> resourceList = HashMultimap.create();
    private MainMenu mainMenu = new MainMenu();
    private Map<Integer, String> credentialMap = new HashMap<Integer, String>(){{
        put(1,"password1");
    }};
    private Map<Integer, Customer> customerMap = new HashMap<Integer, Customer>(){{
        Customer customer = new Customer("zhouxuan", 1);
        customer.setEmail("a@a.c");
        customer.setPhoneNum("029999999");
        put(1, customer);
    }};

    public String getWelcomeMessage() {
        return WELCOME_MESSAGE;
    }

    public Collection<String> getBookNames() {
        return Collections2.transform(resourceList.get(BOOK), new Function<Resource, String>() {
            @Override
            public String apply(Resource myBook) {
                return myBook.getName();
            }
        });
    }

    private String formatStr(Collection<String> names) {
        StringBuffer st = new StringBuffer();
        for (String name : names) {
            st.append("*");
            st.append(name);
            st.append("\n");
        }
        return st.toString();
    }

    public void addResource(Resource resource) {
        resourceList.put(resource.getCategory(), resource);
        mainMenu.addNewBookToOption(resource);
    }

    public Set<String> getMainMenuNames() {
        return mainMenu.getMainMenuName();
    }

    public MainMenu getMainMenu() {
        return mainMenu;
    }

    public boolean choose(String category) {
        if (mainMenu.hasThisCategory(category)) {
            return true;
        }
        return false;
    }

    public Resource checkoutResource(String category, final String resourceName, int customerId) {
        Collection<Resource> filter = filterResources(category, resourceName, INVALIDE_ID);

        if (!filter.isEmpty()) {
            Resource book = filter.iterator().next();
            book.setCheckoutId(customerId);
            return book;

        }
        return null;
    }

    private Collection<Resource> filterResources(String category, final String resourceName, final int valideId) {
        return Collections2.filter(resourceList.get(category), new Predicate<Resource>() {
            @Override
            public boolean apply(Resource resource) {
                return resource.getName().equals(resourceName) && resource.getCheckoutId() == valideId;
            }
        });
    }

    public boolean returnBook(final String name, final int checkoutId) {
        Collection<Resource> filter = filterResources(BOOK, name, checkoutId);

        if(!filter.isEmpty()){
            filter.iterator().next().setCheckoutId(INVALIDE_ID);
            return true;
        }

        return false;
    }

    public String displayWelcomeMessage() {
        String welcomeMessage = getWelcomeMessage();
        System.out.println(welcomeMessage);
        return welcomeMessage;
    }

    public String showBooks() {
        Collection<String> bookNameList = getBookNames();
        String bookNames = formatStr(bookNameList);
        System.out.println(bookNames);
        return bookNames;
    }

    public String showMainMenuInFormat() {
        Set<String> mainMenuNames = getMainMenuNames();
        String nameInFormat = formatStr(mainMenuNames);
        System.out.println(nameInFormat);
        return nameInFormat;
    }

    public List<Resource> getResourcesByCategory(String category) {
        ArrayList<Resource> resources = new ArrayList<Resource>();
        resources.addAll(resourceList.get(category));
        return resources;
    }


    private boolean validateUser(int accountNum, String password) {
        String passwordStored = credentialMap.get(accountNum);
        return password.equals(passwordStored);
    }

    public Resource checkoutBook(int accountNum, String password, String bookName) {
        if(validateUser(accountNum, password)){
           return checkoutResource(BOOK,bookName,accountNum);
        }
        return null;
    }

    public boolean returnBookWithPassword(int accountNum, String password, String bookName) {
        if(validateUser(accountNum, password)){
            return returnBook(bookName,accountNum);
        }
        return false;
    }

    public Customer login(int accountNum, String password) {
        if(validateUser(accountNum,password)){
            return customerMap.get(accountNum);
        }
        return null;
    }
}
